## DBClass originally written by Sergey Efremov on PHP
## Rewritten for Python by Sergey Efremov
import _mysql
import _mysql_exceptions

class Db(object):
    debug = False
    link = None
    line = 0
    result = None
    query_str = None
    connection = False
    stack = []
    
    def connect(self, host, login, passwd, dbname):
        try:
            self.link = _mysql.connect(host=host,user=login, passwd=passwd)
            self.select_db(dbname)
        except _mysql_exceptions.Error as e:
            raise DbError("Cannot establish database connection. "+str(e))
    
    def select_db(self, dbname):
        if not self.link.select_db(dbname):
            self.error()
            return False
        else:
            return True
    
    def query(self, query, unbuffered = True):
        if not self.link:
            return False
        self.query_str = query
        self.line = 0
        if self.debug:
            pass
        try:
            self.link.query(query)
            if unbuffered:
                self.result = self.link.store_result()
            else:
                self.result = self.link.use_result()
        except _mysql_exceptions.Error as e :
            raise DbError("Cannot perform query to database: "+query+". "+str(e))
        return True
    
    def get_cell(self, query):
        self.query(query)
        if self.rows() > 0:
            return result.fetch_row(0)[0][0]
    
    def insert_array(self, table, data): # data - dictionary of fields - values
        fields = []
        values = []
        for k, v in data.iteritems():
            fields.append("`" + str(k) +"`")
            values.append("'" + str(v) + "'")
        return self.query("INSERT INTO `" + table + "` (" + ", ".join(fields) + ") VALUES (" + ", ".join(values) + ")" )
    
    def update_with_array(self, table, data, where = ''):
        fields = []
        for k, v in data.iteritems():
            fields.append("`"+str(k)+"` = '"+str(v)+"'")
        return self.query("UPDATE `"+table+"` SET " + ", ".join(fields) + " WHERE " + where)
    
    def get_row(self, type = 1): #type = 1 assoc, type = 0 tuple
        if not self.result:
            return
        ret = self.result.fetch_row(how = type, maxrows = 0)
        for row in ret:
            yield row
    
    def get_all_force(self):
        pass
    
    def get_all(self, type = "assoc", keyField = False):
        try: 
            ret = self.result.fetch_row(how = 1, maxrows = 0)
            if keyField:
                tmp = {}
                for item in ret:
                    tmp[item[keyField]] = item
                ret = tmp
            return ret 
        except:
            raise DbError("Cannot fetch result of query")
       
    def rows(self):
        if not self.result:
            return False
        return self.result.num_rows() 
    
    def last_id(self):
        if not self.link:
            return False
        return self.link.insert_id()
    
    def error(self):
        pass
    
    def aff_rows(self):
        if not self.link:
            return False
        return self.link.affected_rows()
        
    
    def ping(self):
        link.ping()
    
    def push(self):
        self.stack.append(self.result)
        return True
    
    def pop(self):
        try:
            self.result = self.stack.pop()
            return True
        except:
            return False
    
    
class DbError(Exception):
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)
